/*
 *  TOPPERS Software
 *      Toyohashi Open Platform for Embedded Real-Time Systems
 *
 *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
 *                              Toyohashi Univ. of Technology, JAPAN
 *  Copyright (C) 2004-2008 by Embedded and Real-Time Systems Laboratory
 *              Graduate School of Information Science, Nagoya Univ., JAPAN
 *
 *	The above copyright holders grant permission gratis to use,
 *	duplicate, modify, or redistribute (hereafter called use) this
 *	software (including the one made by modifying this software),
 *	provided that the following four conditions (1) through (4) are
 *	satisfied.
 *
 *	(1) When this software is used in the form of source code, the above
 *    	copyright notice, this use conditions, and the disclaimer shown
 *    	below must be retained in the source code without modification.
 *
 *	(2) When this software is redistributed in the forms usable for the
 *    	development of other software, such as in library form, the above
 *    	copyright notice, this use conditions, and the disclaimer shown
 *    	below must be shown without modification in the document provided
 *    	with the redistributed software, such as the user manual.
 *
 *	(3) When this software is redistributed in the forms unusable for the
 *    	development of other software, such as the case when the software
 *    	is embedded in a piece of equipment, either of the following two
 *   	 conditions must be satisfied:
 *
 *  	(a) The above copyright notice, this use conditions, and the
 *         	disclaimer shown below must be shown without modification in
 *     		the document provided with the redistributed software, such as
 *      	the user manual.
 *
 * 		(b) How the software is to be redistributed must be reported to the
 *     		TOPPERS Project according to the procedure described
 *     		separately.
 *
 *	(4) The above copyright holders and the TOPPERS Project are exempt
 *    	from responsibility for any type of damage directly or indirectly
 *   	caused from the use of this software and are indemnified by any
 *    	users or end users of this software from any and all causes of
 *    	action whatsoever.
 *
 *	THIS SOFTWARE IS PROVIDED "AS IS." THE ABOVE COPYRIGHT HOLDERS AND
 *	THE TOPPERS PROJECT DISCLAIM ANY EXPRESS OR IMPLIED WARRANTIES,
 *	INCLUDING, BUT NOT LIMITED TO, ITS APPLICABILITY TO A PARTICULAR
 *	PURPOSE. IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS AND THE
 *	TOPPERS PROJECT BE LIABLE FOR ANY TYPE OF DAMAGE DIRECTLY OR
 *	INDIRECTLY CAUSED FROM THE USE OF THIS SOFTWARE.
 *
 *  @(#) $Id: log_output.c 1176 2008-07-01 10:24:46Z ertl-hiro $
 */

/*
 *		the formatted output of system log
 */

#include <t_stddef.h>
#include <t_syslog.h>

/*
 *  convert numbers to string
 */
#define CONVERT_BUFLEN	((sizeof(uintptr_t) * CHAR_BIT + 2) / 3)
										/* the maximum length of an uintptr_t number */
static void
convert(uintptr_t val, uint_t radix, const char *radchar,
			uint_t width, bool_t minus, bool_t padzero, void (*putc)(char_t))
{
	char	buf[CONVERT_BUFLEN];
	uint_t	i, j;

	i = 0U;
	do {
		buf[i++] = radchar[val % radix];
		val /= radix;
	} while (i < CONVERT_BUFLEN && val != 0);

	if (minus && width > 0) {
		width -= 1;
	}
	if (minus && padzero) {
		(*putc)('-');
	}
	for (j = i; j < width; j++) {
		(*putc)((char_t)(padzero ? '0' : ' '));
	}
	if (minus && !padzero) {
		(*putc)('-');
	}
	while (i > 0U) {
		(*putc)(buf[--i]);
	}
}

/*
 *  mapping between number and char
 */
static const char raddec[] = "0123456789";
static const char radhex[] = "0123456789abcdef";
static const char radHEX[] = "0123456789ABCDEF";

void
syslog_printf(const char *format, const intptr_t *p_args, void (*putc)(char_t))
{
	char		c;
	uint_t		width;
	bool_t		padzero;
	intptr_t	val;
	const char	*str;

	while ((c = *format++) != '\0') {
		if (c != '%') {
			(*putc)(c);
			continue;
		}

		width = 0U;
		padzero = false;
		if ((c = *format++) == '0') {
			padzero = true;
			c = *format++;
		}
		while ('0' <= c && c <= '9') {
			width = width * 10U + c - '0';
			c = *format++;
		}
		if (c == 'l') {
			c = *format++;
		}
		switch (c) {
		case 'd':
			val = (intptr_t)(*p_args++);
			if (val >= 0) {
				convert((uintptr_t) val, 10U, raddec,
										width, false, padzero, putc);
			}
			else {
				convert((uintptr_t)(-val), 10U, raddec,
										width, true, padzero, putc);
			}
			break;
		case 'u':
			val = (intptr_t)(*p_args++);
			convert((uintptr_t) val, 10U, raddec, width, false, padzero, putc);
			break;
		case 'x':
		case 'p':
			val = (intptr_t)(*p_args++);
			convert((uintptr_t) val, 16U, radhex, width, false, padzero, putc);
			break;
		case 'X':
			val = (intptr_t)(*p_args++);
			convert((uintptr_t) val, 16U, radHEX, width, false, padzero, putc);
			break;
		case 'c':
			(*putc)((char_t)(intptr_t)(*p_args++));
			break;
		case 's':
			str = (const char *)(*p_args++);
			while ((c = *str++) != '\0') {
				(*putc)(c);
			}
			break;
		case '%':
			(*putc)('%');
			break;
		case '\0':
			format--;
			break;
		default:
			break;
		}
	}
}

/*
 *  the output of log information
 */
void
syslog_print(const SYSLOG *p_syslog, void (*putc)(char_t))
{
	switch (p_syslog->logtype) {
	case LOG_TYPE_COMMENT:
		syslog_printf((const char *)(p_syslog->loginfo[0]),
								&(p_syslog->loginfo[1]), putc);
		break;
	case LOG_TYPE_ASSERT:
		syslog_printf("%s:%u: Assertion `%s' failed.",
								&(p_syslog->loginfo[0]), putc);
		break;
	}
}

/*
 *  the output of log lost message 
 */
void
syslog_lostmsg(uint_t lost, void (*putc)(char_t))
{
	intptr_t	lostinfo[1];

	lostinfo[0] = (intptr_t) lost;
	syslog_printf("%d messages are lost.", lostinfo, putc);
	(*putc)('\n');
}
